#include <vector>

#include <openssl/bn.h>
#include <openssl/ec.h>

#include "starkware/crypto/elliptic_curve_constants.h"

using ValueType = starkware::BigInt<4>;

/**
 * @brief Given x coordinate, calculate y on elliptic curve (y^2 = x^3 + ax + b)
 * 
 * @param group       underlying EC_GROUP object
 * @param x           BIGNUM for the x-coordinate
 * @param alpha       alpha of Elliptic Curve
 * @param beta        beta of Elliptic Curve
 * @param mod         modulo (prime) of Elliptic Curve
 * @param public_key  Public key point P = (x, y)
 * @return int        1 on success
 */
int GetPointFromX(
    const EC_GROUP* group, 
    const BIGNUM* x, const BIGNUM* alpha, 
    const BIGNUM* beta, const BIGNUM* mod, 
    EC_POINT* public_key);
/**
 * @brief Converts shift_point (P0) and precalculated 2^th powers of P1, P2, P3, P4 of PedersenHash to EC_POINT
 * 
 * @param group       underlying EC_GROUP object
 * @param shift_point EC_POINT for P0
 * @param points      vector of EC_POINT for P1, P2, P3, P4
 * @return int        1 on success
 */
int EcConstants2EC_POINT(const EC_GROUP* group, EC_POINT* shift_point, std::vector<EC_POINT*> points);
int VT2BN(const ValueType& vt_x, BIGNUM* bn_x);
ValueType BN2VT(const BIGNUM* bn_x);
int EcPoint2EC_POINT(
    const EC_GROUP* group,
    const starkware::EcPoint<starkware::PrimeFieldElement> sw_point,
    EC_POINT* ec_point);
